package com.tuanzi.loan.business.service.product.space.impl;

import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.domain.Page;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.retry.RetryException;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tuanzi.loan.business.entity.product.space.LoanProductSpace;
import com.tuanzi.loan.business.entity.product.space.LoanProductSpaceProduct;
import com.tuanzi.loan.business.repository.product.space.LoanProductSpaceProductRepository;
import com.tuanzi.loan.business.repository.product.space.LoanProductSpaceRepository;
import com.tuanzi.loan.business.service.product.space.LoanProductSpaceService;
import com.tuanzi.loan.core.aspect.Debug;
import com.tuanzi.loan.core.vo.PageSearcher;
import com.tuanzi.loan.vo.ManualSortProduct;
import com.tuanzi.loan.vo.request.product.space.LoanProductSpaceSearchRequest;
import com.tuanzi.loan.vo.response.product.space.LoanProductSpaceSearchResponse;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Debug
@Service
@Transactional
@Retryable(value = { RetryException.class })
public class LoanProductSpaceServiceImpl implements LoanProductSpaceService {

	@Autowired
	private TaskExecutor taskExecutor;
	@Autowired
	private LoanProductSpaceRepository loanProductSpaceRepository;
	@Autowired
	private LoanProductSpaceProductRepository loanSpaceProductRepository;
	@Autowired
	private StringRedisTemplate stringRedisTemplate;

	@Override
	public Page<LoanProductSpaceSearchResponse> list(PageSearcher<LoanProductSpaceSearchRequest> pageSearcher) {
		return loanProductSpaceRepository.list(pageSearcher.getSearchCondition(), pageSearcher.getPageable());
	}

	@Override
	public LoanProductSpace findOneById(Long id) {
		return loanProductSpaceRepository.findOne(id);
	}

	@Override
	public LoanProductSpace save(LoanProductSpace space, List<LoanProductSpaceProduct> loanSpaceProducts) {
		if (null != space.getId()) {
			space.setManualSortProducts(null);
			loanSpaceProductRepository.deleteBySpaceId(space.getId());
		}

		if (CollectionUtils.isNotEmpty(loanSpaceProducts)) {
			JSONArray array = new JSONArray();
			loanSpaceProducts.stream().map(product -> ManualSortProduct.builder().productId(product.getProductId()).position(product.getPosition()).build()).forEach(product -> {
				JSONObject obj = (JSONObject) JSON.toJSON(product);
				array.add(obj);
			});
			space.setManualSortProducts(array.toJSONString());
		}

		LoanProductSpace loanSpace = loanProductSpaceRepository.save(space);

		loanSpaceProducts.stream().forEach(product -> {
			product.setSpaceId(loanSpace.getId());
			loanSpaceProductRepository.save(product);
		});

		cleanSpaceRedisBy(loanSpace.getId());
		return loanSpace;
	}

	@Override
	public List<LoanProductSpace> findAllByType(Integer type) {
		return loanProductSpaceRepository.findAllByType(type);
	}

	@Override
	public void cleanSpaceRedisBy(Long id) {
		taskExecutor.execute(() -> {
			List<LoanProductSpace> loanSpaces = loanProductSpaceRepository.findAll();
			loanSpaces.stream().map(LoanProductSpace::getId).forEach(x -> stringRedisTemplate.delete("loan-app:space:" + id));
			loanSpaces.stream().map(LoanProductSpace::getId).forEach(x -> stringRedisTemplate.delete("loan-app:topic-space:" + id));

		});
	}

	@Override
	public LoanProductSpace findBySpaceId(Long spaceId) {
		return loanProductSpaceRepository.findBySpaceId(spaceId);
	}
}
